<?php
/**
 * XController 是 CController 扩展类，以满足应用程序需求
 * 所有 controller 类必须继承此类
 *
 * @author     mole <mole1230@gmail.com>
 * @version    $Id: XController.php 86 2011-01-13 09:23:11Z mole1230 $
 */

class XController extends CController
{
	const ERROR = 'error';
	const INFO = 'info';
	
	/**
	 * 默认布局 文件
	 *
	 * @var string
	 */
	public $layout = '//layouts/main';

	/**
	 * 当前页面包屑数组，参考{@link CBreadcrumbs::links}
	 *
	 * @var array
	 */
	public $breadcrumbs = array();
	
	/**
	 * 用户信息
	 * 
	 * @var CWebUser
	 */
	public $user;
	
	/**
	 * @var array
	 */
	public $menu;
	
	/**
	 * @var CHttpRequest
	 */
	public $request;

	/**
	 * @var string
	 */
	private $_jsId;

	/**
	 * 参考 {@link CClientScript} 位置定义
	 *
	 * @var int
	 */
	private $_jsPosition;

	/**
	 * 初始化 CWebUser 对象。
	 *
	 * @param string $id
	 * @param string $module
	 */
	public function __construct($id, $module = null)
	{
		parent::__construct($id, $module);
		$this->user = Yii::app()->getUser();
		$this->request = Yii::app()->getRequest();
		$this->menu = Yii::app()->params['menu'];
	}
	
	/**
	 * @see parent::filters()
	 */
	public function filters()
	{
		return array(
			'requireLogin - login, logout, captcha',
			'accessControl - login, logout, captcha'
		);
	}
	
	/**
	 * 强制登陆
	 * 
	 * @param CFilterChain $filterChain
	 */
	public function filterRequireLogin($filterChain)
	{
		if ($this->user->getIsGuest()) {
			$this->redirect($this->user->loginUrl);
		}
		
		$filterChain->run();
	}
	
	/**
	 * 权限控制
	 * 
	 * @param CFilterChain $filterChain
	 */
	public function filterAccessControl($filterChain)
	{
		$acls = $this->assembleMenu($this->user->admin_role_id, $this->user->acls);
		$ctrl = $this->getId();
		$act  = $this->getAction()->getId();
		
		$excludeCtrls = array('site');
		$excludeActs = array('unique', 'exist');
		if (!in_array($ctrl, $excludeCtrls) && !in_array($act, $excludeActs) && !isset($acls[$ctrl]['actions'][$act])) {
			throw new CHttpException(403);
		}
		
		$filterChain->run();
	}

	/**
	 * 生成资源URL地址，方便移值和资源分离。
	 *
	 * @param string $asset
	 * @param bool $isVersion 是否显示版本号，主要用于资源更新立即生效
	 * @return string
	 */
	public function asset($asset, $isVersion = false)
	{
		return $asset;
	}

	/**
	 * 捕获JS代码，在页面输出时，将其插入指定位置。
	 *
	 * @param string $id 唯一标识符，如果标识符相同，后面的会覆盖前面的。
	 * @param int $position 参考 {@link CClientScript} 位置定义
	 */
	public function beginJs($id = '', $position = CClientScript::POS_READY)
	{
		if ($id == '') {
			$id = uniqid('_js_');
		}
		$this->_jsId = $id;
		$this->_jsPosition = $position;

		ob_start();
		ob_implicit_flush(false);
	}

	/**
	 * 与 {@link beginJs} 成对出现，捕获其间代码
	 */
	public function endJs()
	{
		$clip = strip_tags(ob_get_clean());
		$cs = Yii::app()->clientScript;
		$cs->registerScript($this->_jsId, $clip, $this->_jsPosition);
		$this->_jsId = null;
		$this->_jsPosition = null;
	}

	/**
	 * 统一AJAX返回数据类型。
	 *
	 * @param string $code 返回代码，以  A 开头表示成功，而以其它字母开头均表示失败。
	 * @param array $data
	 * @param bool $return
	 */
	public function responseJson($code = 'A00001', $data = array() , $return = false)
	{
		$json = json_encode(array(
			'code' => $code,
			'data' => $data
		));
		if ($return) {
			return $json;
		}

		echo $json;
		Yii::app()->end();
	}
	
//	/**
//	 * 屏蔽 notice 错误
//	 * 
//	 * @see {@link parent::renderPartial()}
//	 */
//	public function renderPartial($view, $data = null, $return = false, $processOutput = false)
//	{
//		$o = error_reporting(error_reporting() & ~E_NOTICE);
//		$out = parent::renderPartial();
//		error_reporting($o);
//		
//		return $out;
//	}
	
	/**
	 * @param string|array $msg
	 */
	public function error($msg)
	{
		if (is_string($msg)) {
			$msg = array($msg);
		}
		
		$msg = F::arrayFlat($msg);
		$this->user->setFlash(self::ERROR, $msg);
	}
	
	/**
	 * @param string|array $msg
	 */
	public function info($msg)
	{
		if (is_array($msg)) {
			$msg = implode(' ', $msg);
		}

		$this->user->setFlash(self::INFO, $msg);
	}
	
	/**
	 * @return bool
	 */
	public function hasError()
	{
		return $this->user->hasFlash(self::ERROR);
	}
	
	/**
	 * @return bool
	 */
	public function hasInfo()
	{
		return $this->user->hasFlash(self::INFO);
	}
	
	/**
	 * @return array
	 */
	public function getError()
	{
		return $this->user->getFlash(self::ERROR);
	}
	
	/**
	 * @return string
	 */
	public function getInfo()
	{
		return $this->user->getFlash(self::INFO);
	}
	
	/**
	 * 提取用户权限菜单
	 * 
	 * @param int $rank
	 * @param array $acls
	 * @return array
	 */
	public function assembleMenu($rank, $acls)
	{
		if ($rank == AdminRole::SUPER_RANK_ID) {
			return $this->menu;
		}
		
		$menu = array();
		foreach ($this->menu as $ctrlKey => $ctrl) {
			if (isset($acls['ctrls'][$ctrlKey])) {
				$menu[$ctrlKey] = $ctrl;
				continue;
			}

			$acts = array();
			foreach ($ctrl['actions'] as $actKey => $act) {
				if (isset($act['acl']) && $act['acl'] === false || isset($acls['acts'][$ctrlKey][$actKey])) {
					$acts[$actKey] = true;
				}
			}
			if (!empty($acts)) {
				$menu[$ctrlKey] = $ctrl;
				$menu[$ctrlKey]['actions'] = array_intersect_key($ctrl['actions'], $acts);
			}
		}
		
		return $menu;
	}
}
